package bll

import (
	"fmt"
	"jgt-wallet/src/model"
	"jgt-wallet/src/schema"
	"sync"
	"time"
)

// 订单管理
type Order struct {
	AlipayAppBll *AlipayApp   `inject:""`
	WechatAppBll *WechatApp   `inject:""`
	OrderModel   model.IOrder `inject:"IOrder"`
	sync.Mutex
}

// QueryOrder 查询订单
func (a *Order) QueryOrder(params *schema.OrderQueryParam) (int64, []*schema.Order, error) {
	return a.OrderModel.QueryOrder(params)
}

// GetOrder 获取订单
func (a *Order) GetOrder(recordId string) (*schema.Order, error) {

	var (
		pk    map[string]interface{}
		order *schema.Order
		err   error
	)
	pk = map[string]interface{}{
		"record_id": recordId,
	}

	order, err = a.OrderModel.GetOrder(pk)
	return order, err
}

// GetOrderByOrderId 根据订单获取支付记录
func (a *Order) GetOrderByOrderId(orderId string) (*schema.Order, error) {
	var (
		data []*schema.Order
		ps   = new(schema.OrderQueryParam)
		err  error
	)
	ps.OrderID = orderId
	ps.Page = true
	ps.PageFrom = 0
	ps.PageSize = 1
	ps.Sort = []string{
		"-_id",
	}
	_, data, err = a.QueryOrder(ps)
	if len(data) > 0 {
		return data[0], err
	} else {
		return nil, err
	}
}

func (a *Order) GetOrderResult(orderId string) (*schema.OrderQueryResult, error) {
	var (
		order  *schema.Order
		result = new(schema.OrderQueryResult)
		err    error
	)

	order, err = a.GetOrderByOrderId(orderId)
	if err != nil {
		return nil, err
	}

	if order == nil {
		result.Result = schema.RESULT_NOTFOUND
	} else {
		if order.Status == schema.ORDER_STATUS_NEW ||
			order.Status == schema.ORDER_STATUS_CHECK ||
			order.Status == schema.ORDER_STATUS_CALLBACK ||
			order.Status == schema.ORDER_STATUS_ERROR {
			switch order.PayType {
			case schema.PAY_TYPE_ALIPAY_APP:
				err = a.AlipayAppBll.QueryOrderResult(order.RecordID)
			case schema.PAY_TYPE_WECHAT_APP:
				err = a.WechatAppBll.QueryOrderResult(order.RecordID)
			}
			if err != nil {
				return nil, err
			}
			order, err = a.GetOrderByOrderId(orderId)
		}

		result.PayType = order.PayType
		result.RecordID = order.RecordID
		result.OrderID = order.OrderID
		result.Price = order.Price
		result.RealPrice = order.RealPrice

		if order.Status == schema.ORDER_STATUS_SUCCESS {
			result.Result = schema.RESULT_SUCCESS
		} else if order.Status == schema.ORDER_STATUS_FAIL {
			result.Result = schema.RESULT_FAIL
		} else if order.Status == schema.ORDER_STATUS_CANCEL {
			result.Result = schema.RESULT_CANCEL
		} else {
			result.Result = schema.RESULT_ERROR
		}

	}

	return result, nil
}

// CreateOrder 创建订单
func (a *Order) CreateOrder(item *schema.Order) error {
	a.Lock()
	defer a.Unlock()

	item.Created = time.Now().Unix()
	item.Checked = 0
	item.Callbacked = 0

	item.Status = schema.ORDER_STATUS_NEW
	item.CheckStatus = schema.CHECK_STATUS_NONE
	item.CallbackStatus = schema.CALLBACK_STATUS_NONE

	if item.PayData == "" {
		return fmt.Errorf("缺少支付数据")
	}
	return a.OrderModel.CreateOrder(item)
}

// CheckOrder 同步回调
func (a *Order) CheckOrder(recordId, checkData string, checkStatus int) (string, error) {
	a.Lock()
	defer a.Unlock()
	var (
		pk, info map[string]interface{}
		order    *schema.Order
		err      error
	)
	if checkData == "" {
		return "", fmt.Errorf("缺少必要参数")
	}
	order, err = a.GetOrder(recordId)
	if err != nil || order == nil {
		return "", err
	}
	pk = map[string]interface{}{
		"record_id": recordId,
	}
	if order.CheckStatus == schema.CHECK_STATUS_NONE {
		info = map[string]interface{}{
			"check_data":   checkData,
			"check_status": checkStatus,
			"checked":      time.Now().Unix(),
		}
	}
	switch order.Status {
	case schema.ORDER_STATUS_NEW:
		info["status"] = schema.ORDER_STATUS_CHECK
		err = a.OrderModel.UpdateOrder(pk, info)
	case schema.ORDER_STATUS_CHECK:
		return "", fmt.Errorf("订单已回调")
	case schema.ORDER_STATUS_CALLBACK:
		return "", fmt.Errorf("订单已异步回调")
	case schema.ORDER_STATUS_SUCCESS:
		return "", fmt.Errorf("订单已完成")
	case schema.ORDER_STATUS_CANCEL:
		if order.CheckStatus == schema.CHECK_STATUS_NONE {
			info["status"] = schema.ORDER_STATUS_ERROR
			err = a.OrderModel.UpdateOrder(pk, info)
		}
		return "", fmt.Errorf("订单已取消")
	default:
		if order.CheckStatus == schema.CHECK_STATUS_NONE {
			info["status"] = schema.ORDER_STATUS_ERROR
			err = a.OrderModel.UpdateOrder(pk, info)
		}
		return "", fmt.Errorf("订单异常")
	}
	return order.OrderID, nil
}

// CallbackOrder 异步回调
func (a *Order) CallbackOrder(recordId, tradeId, callbackData string, callbackStatus int, price int64) error {
	a.Lock()
	defer a.Unlock()
	var (
		pk, info map[string]interface{}
		order    *schema.Order
		err      error
	)
	if callbackData == "" {
		return fmt.Errorf("缺少必要参数")
	}
	order, err = a.GetOrder(recordId)
	if err != nil {
		return err
	}
	pk = map[string]interface{}{
		"record_id": recordId,
	}
	if order.CheckStatus == schema.CHECK_STATUS_NONE {
		info = map[string]interface{}{
			"callback_data":   callbackData,
			"callback_status": callbackStatus,
			"callbacked":      time.Now().Unix(),
			"trade_id":        tradeId,
			"real_price":      price,
		}
	}
	switch order.Status {
	case schema.ORDER_STATUS_NEW:
		info["status"] = schema.ORDER_STATUS_CALLBACK
		err = a.OrderModel.UpdateOrder(pk, info)
	case schema.ORDER_STATUS_CHECK:
		if callbackStatus == schema.CALLBACK_STATUS_SUCCESS {
			info["status"] = schema.ORDER_STATUS_SUCCESS
		} else if callbackStatus == schema.CALLBACK_STATUS_FAIL {
			info["status"] = schema.ORDER_STATUS_FAIL
		} else {
			info["status"] = schema.ORDER_STATUS_CALLBACK
		}
		err = a.OrderModel.UpdateOrder(pk, info)
	case schema.ORDER_STATUS_CALLBACK:
		return fmt.Errorf("订单已回调")
	case schema.ORDER_STATUS_SUCCESS:
		return fmt.Errorf("订单已完成")
	case schema.ORDER_STATUS_CANCEL:
		if order.CallbackStatus == schema.CALLBACK_STATUS_NONE {
			info["status"] = schema.ORDER_STATUS_ERROR
			err = a.OrderModel.UpdateOrder(pk, info)
		}
		return fmt.Errorf("订单已取消")
	default:
		if order.CallbackStatus == schema.CALLBACK_STATUS_NONE {
			info["status"] = schema.ORDER_STATUS_ERROR
			err = a.OrderModel.UpdateOrder(pk, info)
		}
		return fmt.Errorf("订单异常")
	}
	return nil
}

// UpdateOrder 更新订单信息
func (a *Order) UpdateOrder(item *schema.Order) error {
	var (
		pk   = map[string]interface{}{}
		info = map[string]interface{}{}
	)

	if item.RecordID == "" {
		return fmt.Errorf("缺少RecordID")
	}
	pk["record_id"] = item.RecordID

	if v := item.Status; v != 0 {
		info["status"] = v
	}
	if v := item.TradeID; v != "" {
		info["trade_id"] = v
	}
	if v := item.RealPrice; v != 0 {
		info["real_price"] = v
	}
	if v := item.QueryData; v != "" {
		info["query_data"] = v
	}

	return a.OrderModel.UpdateOrder(pk, info)
}

// CancelOrder 取消订单
func (a *Order) CancelOrder(orderId string) error {
	var (
		result *schema.OrderQueryResult
		order  *schema.Order
		pk     = map[string]interface{}{}
		info   = map[string]interface{}{}
		err    error
	)
	result, err = a.GetOrderResult(orderId)
	if err != nil {
		return err
	}
	if result.Result == schema.RESULT_SUCCESS {
		return fmt.Errorf("交易已成功,不能取消")
	} else {
		order, _ = a.GetOrderByOrderId(orderId)
		pk["record_id"] = order.RecordID
		info["status"] = schema.ORDER_STATUS_CANCEL
		return a.OrderModel.UpdateOrder(pk, info)
	}
}
